package org.streets.context;

import static org.streets.context.HiveConstants.APPLICATION_CHARSET;
import static org.streets.context.HiveConstants.APPLICATION_COPYRIGHT;
import static org.streets.context.HiveConstants.APPLICATION_NAME;
import static org.streets.context.HiveConstants.APPLICATION_VENDOR;
import static org.streets.context.HiveConstants.APPLICATION_VERSION;

import java.util.List;

import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.ObjectProvider;
import org.apache.tapestry5.ioc.OrderedConfiguration;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.InjectService;
import org.apache.tapestry5.ioc.annotations.Marker;
import org.apache.tapestry5.ioc.annotations.NotLazy;
import org.apache.tapestry5.ioc.annotations.Primary;
import org.apache.tapestry5.ioc.services.PipelineBuilder;
import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.slf4j.Logger;
import org.streets.context.definition.ContextDefinition;
import org.streets.context.internal.ContextDefinitionImpl;
import org.streets.context.internal.ContextSymbol;
import org.streets.context.internal.ContextSymbolProvider;
import org.streets.context.internal.ResourceLocatorImpl;

/**
 * Main streets application module
 * @author dzb
 */
public class HiveContextModule {
    /**
     * Initializer pipeline
     */
	private PipelineBuilder pipelineBuilder;
	/**
     * 
     * @param binder
     */
	public static void bind(ServiceBinder binder) {
		binder.bind(ResourceLocator.class, ResourceLocatorImpl.class);
	}
	
	public HiveContextModule(PipelineBuilder pipelineBuilder) {
		this.pipelineBuilder = pipelineBuilder;
	}
	/**
     * 
     * @param configuration
     * @param store
     */
    public void contributeSymbolSource(
            OrderedConfiguration<SymbolProvider> configuration,
            @InjectService("ContextSymbol") SymbolProvider store) {
    	
    	configuration.add("ContextSymbol", store, "before:ApplicationDefaults");
    }
    
    /**
     * Build the actual provider for SymbolStore services
     * @param logger logging facility
     * @return the {@link ObjectProvider} delegated to lookup objects
     */
    public ContextSymbolProvider buildContextSymbol(Logger logger, final List<ContextSymbol> symbols) {
        
        return new ContextSymbolProvider(logger, symbols);
    }

    /**
     * Context 定义服务
     * @param logger
     * @param registryShutdownHub
     * @return
     */
    @NotLazy
    public ContextDefinition buildContextDefinition(Logger logger, RegistryShutdownHub registryShutdownHub) {
    	
    	final ContextDefinitionImpl definition = new ContextDefinitionImpl(logger);
    	
    	registryShutdownHub.addRegistryShutdownListener(new RegistryShutdownListener(){

			public void registryDidShutdown() {
				definition.clear();				
			}    		
    	});
    	
    	return definition;
    }
	
    /**
     * Initializes the application, using a pipeline of {@link org.apache.tapestry5.services.ApplicationInitializer}s.
     */
    @Marker(Primary.class)
    public HiveInitializer buildHiveInitializer(Logger logger, List<HiveInitializerFilter> configuration) {
        
        HiveInitializer terminator = new HiveInitializerTerminator(logger);

        return pipelineBuilder.build(logger, HiveInitializer.class, HiveInitializerFilter.class,
                                     configuration, terminator);
    }
    /**
     * Default settings for streets application
     * @param configuration
     */
    public void contributeFactoryDefaults(MappedConfiguration<String, String> configuration) {
    	configuration.add(APPLICATION_NAME, "STREETS POWERED APPLICATION");
    	configuration.add(APPLICATION_VERSION, "2.0.0");
    	configuration.add(APPLICATION_VENDOR, "HiveTech Co.ltd");
    	configuration.add(APPLICATION_CHARSET, "utf-8");    	
    	configuration.add(APPLICATION_COPYRIGHT, "Copyright(2010) Streets Alliance. All rights reserved. ");
    }
    
    private class HiveInitializerTerminator implements HiveInitializer {
    	
    	Logger logger;
    	
    	HiveInitializerTerminator(Logger logger) {
    		this.logger = logger;
    	}

		public void initialize(HiveContext context) {

			logger.info("-> All initializers have been initialized ... ");
		}    	
    }
}
